#include <iostream>
#include <string>
#include <vector>

class VideoFile
{
private:
    std::string filename;
    std::string format;
    std::string content;
public:
    VideoFile(std::vector<std::string> info)
    {
        filename = info[0];
        format = info[1];
        content = info[2];
    }
    VideoFile(std::string filename_)
    {
        filename = filename_;
        format = filename.substr(filename.size()-3, 3);
        content = filename + " content";
    }
    std::vector<std::string> getAllInfo()
    {
        std::vector<std::string> ret;
        ret.push_back(filename);
        ret.push_back(format);
        ret.push_back(content);
        return ret;
    }
    void save()
    {
        std::cout<<"Save file to: "<<filename<<std::endl;
        std::cout<<"Format: "<<format<<std::endl;
        std::cout<<"Content: "<<content<<std::endl;
    }
};

class SourceCodeC
{
private:
    std::vector<std::string> info;
public:
    SourceCodeC(std::vector<std::string> allinfo)
    {
        info = std::move(allinfo);
    }
    std::vector<std::string> content()
    {
        return info;
    }
};

class CodecFactory
{
public:
    SourceCodeC* extract(VideoFile* filename)
    {
        std::cout<<"CodecFactory extract"<<std::endl;
        return new SourceCodeC(filename->getAllInfo());
    }
};

class CompressionCodec
{
public:
    virtual std::string filename(std::string data) = 0;
    virtual std::string format(std::string data) = 0;
    virtual std::string codec(std::string data) = 0;
};

class MPEG4CompressionCodec : public CompressionCodec
{
public:
    std::string filename(std::string data) override
    {
        std::string tmp = data.substr(0, data.size()-4);
        return tmp + ".mp4";
    }
    std::string format(std::string data) override
    {
        return "mp4";
    }
    std::string codec(std::string data) override
    {
        return " MPEG4 " + data;
    }
};

class OggCompressionCodec : public CompressionCodec
{
public:
    std::string filename(std::string data) override
    {
        std::string tmp = data.substr(0, data.size()-3);
        return tmp + ".ogg";
    }
    std::string format(std::string data) override
    {
        return "ogg";
    }
    std::string codec(std::string data) override
    {
        return " OGG " + data;
    }
};

class BitrateReader
{
public:
    static std::vector<std::string> read(std::string filename, SourceCodeC* sourceCodec)
    {
        std::cout<<"BitrateReader read"<<std::endl;
        return sourceCodec->content();
    }
    static std::vector<std::string> convert(std::vector<std::string> buffer, CompressionCodec* destinationCodec)
    {
        std::cout<<"BitrateReader convert"<<std::endl;
        std::vector<std::string> ret;
        ret.push_back(destinationCodec->filename(buffer[0]));
        ret.push_back(destinationCodec->format(buffer[1]));
        ret.push_back(destinationCodec->codec(buffer[2]));
        return ret;
    }
};


class VideoConverter
{
public:
    VideoFile* convert(std::string filename, std::string format)
    {
        VideoFile* file = new VideoFile(filename);
        auto codecFactory = new CodecFactory();
        SourceCodeC* sourceCodec = codecFactory->extract(file);
        CompressionCodec* destinationCodec = nullptr;
        if (format == "mp4")
        {
            destinationCodec = new MPEG4CompressionCodec();
        } else{
            destinationCodec = new OggCompressionCodec();
        }
        std::vector<std::string> buffer = BitrateReader::read(filename, sourceCodec);
        std::vector<std::string> result = BitrateReader::convert(buffer, destinationCodec);
        return new VideoFile(result);
    }

};

int main() {
    VideoConverter* convertor = new VideoConverter();
    VideoFile* mp4 = convertor->convert("video.ogg", "mp4");
    mp4->save();
    return 0;
}
